%%%-------------------------------------------------------------------
%%% @author Rain
%%% @copyright (C) 2022, <COMPANY>
%%% @doc 排行榜通用数据模块 - 一般不进行修改
%%%
%%% @end
%%% Created : 31. 3月 2022 17:29
%%%-------------------------------------------------------------------
-module(rank).
-author("Rain").
-include("rank.hrl").


%% API
-export([create_rank_proc/0,
    submit/2,
    get_rank_data/2]).

%% @doc 批量创建排行榜相关进程
create_rank_proc() ->
    create_rank_proc(?RANK_TYPE_LIST).
create_rank_proc(TypeList) ->
    create_rank_sup(),
    [create_rank_svr(Type) || Type <- TypeList].

%% @doc 创建排行榜进程监控者
create_rank_sup() ->
    case whereis(rank_sup) of
        undefined ->
            io:format("Create RankSup ~n"),
            entrace_sup:start_child_sup_rank(),
            io:format("Create RankSup Succ ~n");
        _ ->
            pass
    end.

%% @doc 创建排行榜进程
create_rank_svr(RankType) ->
    case whereis(?RANK_SVR_NAME(RankType)) of
        undefined ->
            io:format("Start RankSvr ~p~n", [RankType]),
            Ret = rank_sup:start_rank_svr(RankType),
            io:format("Start RankSvr ~p~n Ret ~p~n", [RankType, Ret]);
        _ ->
            pass
    end.

%% @doc 上传数据到排行榜
submit(Type, UserData) ->
    BriefKeys = lists:usort(get_normal_brief_key() ++ get_ext_brief_key(Type)),
    Briefs = get_rank_briefs(BriefKeys, UserData),
    RankData = rank_util:make_rank_data(Type, UserData, #rank_data{briefs = Briefs}),
    gen_server:cast(?RANK_SVR_NAME(Type), {submit, RankData}).

%% @doc 根据BriefKeys获取排行榜Briefs
get_rank_briefs(BriefKeys, UserData) ->
    get_rank_briefs(BriefKeys, UserData, #{}).
get_rank_briefs([], _UserData, Acc) ->
    Acc;
get_rank_briefs([BriefKey | T], UserData, Acc) ->
    case rank_util:get_rank_brief_one(BriefKey, UserData) of
        undef ->
            get_rank_briefs(T, UserData, Acc);
        Value ->
            get_rank_briefs(T, UserData, Acc#{BriefKey => Value})
    end.


%% @doc 不同的排行榜类型根据获取表格提供的额外BriefKey
%% TODO 目前简单写死一些数据, 有表格数据时这块是通用的，无需修改
get_ext_brief_key(?RANK_TYPE_LEVEL) ->
    [?RANK_BRIEF_KEY_ICON];
get_ext_brief_key(?RANK_TYPE_POWER) ->
    [?RANK_BRIEF_KEY_SEX];
get_ext_brief_key(_) ->
    [].

%% @doc 通用BriefKey
get_normal_brief_key() ->
    [?RANK_BRIEF_KEY_NAME, ?RANK_BRIEF_KEY_LEVEL].

%% @doc 获取前N名的排行榜数据
get_rank_data(RankType, TopN) ->
    TabName = ?ETS_RANK(RankType),
    case ets:whereis(TabName) of
            undefined ->
                Err = io_lib:format("RankType ~w Ranks Not Find", [RankType]),
                logger:error(Err),
                [];
            _ ->
                Fun =
                    fun(_, {Rank, AccList}) when Rank >= TopN ->
                        {break, {Rank, AccList}};
                        (RankData, {Rank, AccList}) ->
                            Rank1 = Rank + 1,
                            {Rank1, [RankData#rank_data{rank = Rank1} | AccList]}
                    end,
                {_, Ranks} = ets_util:foldl(Fun, {0, []}, ?ETS_RANK(RankType)),
                lists:reverse(Ranks)
    end.

